﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IPC.Communication.Core;
using IPC.Communication.Core.Net;
using IPC.Communication.Reflection;

namespace IPC.Communication.Profinet.Omron
{
    public class OmronFinsUdp : NetworkUdpDeviceBase
    {
        public override string IpAddress
        {
            get
            {
                return base.IpAddress;
            }
            set
            {
                base.IpAddress = value;
                DA1 = Convert.ToByte(base.IpAddress.Substring(base.IpAddress.LastIndexOf(".") + 1));
            }
        }
        private byte _icf = 128;
        private byte _rsv = 0;
        private byte _gct = 2;
        private byte _dna = 0;
        private byte _da1 = 19;
        private byte _da2 = 0;
        private byte _sna = 0;
        private byte _sa1 = 13;
        private byte _sid = 0;
        private int _readSplits = 500;
        public byte ICF
        {
            get { return _icf; }
            set { _icf = value; }
        }


        public byte RSV
        {
            get { return _rsv; }
            private set { _rsv = value; }
        }


        public byte GCT
        {
            get { return _gct; }
            set { _gct = value; }
        }


        public byte DNA
        {
            get { return _dna; }
            set { _dna = value; }
        }


        public byte DA1
        {
            get { return _da1; }
            set { _da1 = value; }
        }


        public byte DA2
        {
            get { return _da2; }
            set { _da2 = value; }
        }


        public byte SNA
        {
            get { return _sna; }
            set { _sna = value; }
        }


        public byte SA1
        {
            get { return _sa1; }
            set { _sa1 = value; }
        }


        public byte SA2
        {
            get;
            set;
        }

        public byte SID
        {
            get { return _sid; }
            set { _sid = value; }
        }


        public int ReadSplits
        {
            get { return _readSplits; }
            set { _readSplits = value; }
        }


        public OmronFinsUdp(string ipAddress, int port)
            : this()
        {
            IpAddress = ipAddress;
            Port = port;
        }

        public OmronFinsUdp()
        {
            base.WordLength = 1;
            base.ByteTransform = new ReverseWordTransform();
            base.ByteTransform.DataFormat = DataFormat.CDAB;
            base.ByteTransform.IsStringReverseByteWord = true;
        }

        private byte[] PackCommand(byte[] cmd)
        {
            byte[] array = new byte[10 + cmd.Length];
            array[0] = ICF;
            array[1] = RSV;
            array[2] = GCT;
            array[3] = DNA;
            array[4] = DA1;
            array[5] = DA2;
            array[6] = SNA;
            array[7] = SA1;
            array[8] = SA2;
            array[9] = SID;
            cmd.CopyTo(array, 10);
            return array;
        }

        protected override byte[] PackCommandWithHeader(byte[] command)
        {
            return PackCommand(command);
        }

        protected override OperateResult<byte[]> UnpackResponseContent(byte[] send, byte[] response)
        {
            return OmronFinsNetHelper.UdpResponseValidAnalysis(response);
        }

        [HslMqttApi("ReadByteArray", "")]
        public override OperateResult<byte[]> Read(string address, ushort length)
        {
            return OmronFinsNetHelper.Read(this, address, length, ReadSplits);
        }

        [HslMqttApi("WriteByteArray", "")]
        public override OperateResult Write(string address, byte[] value)
        {
            return OmronFinsNetHelper.Write(this, address, value);
        }

        [HslMqttApi("ReadString", "")]
        public override OperateResult<string> ReadString(string address, ushort length)
        {
            return base.ReadString(address, length, Encoding.UTF8);
        }

        [HslMqttApi("WriteString", "")]
        public override OperateResult Write(string address, string value)
        {
            return base.Write(address, value, Encoding.UTF8);
        }

        [HslMqttApi("ReadBoolArray", "")]
        public override OperateResult<bool[]> ReadBool(string address, ushort length)
        {
            return OmronFinsNetHelper.ReadBool(this, address, length, ReadSplits);
        }

        [HslMqttApi("WriteBoolArray", "")]
        public override OperateResult Write(string address, bool[] values)
        {
            return OmronFinsNetHelper.Write(this, address, values);
        }

        [HslMqttApi(ApiTopic = "Run", Description = "将CPU单元的操作模式更改为RUN，从而使PLC能够执行其程序。")]
        public OperateResult Run()
        {
            return OmronFinsNetHelper.Run(this);
        }

        [HslMqttApi(ApiTopic = "Stop", Description = "将CPU单元的操作模式更改为PROGRAM，停止程序执行。")]
        public OperateResult Stop()
        {
            return OmronFinsNetHelper.Stop(this);
        }

        [HslMqttApi(ApiTopic = "ReadCpuUnitData", Description = "读取CPU的一些数据信息，主要包含型号，版本，一些数据块的大小。")]
        public OperateResult<OmronCpuUnitData> ReadCpuUnitData()
        {
            return OmronFinsNetHelper.ReadCpuUnitData(this);
        }

        [HslMqttApi(ApiTopic = "ReadCpuUnitStatus", Description = "读取CPU单元的一些操作状态数据，主要包含运行状态，工作模式，错误信息等。")]
        public OperateResult<OmronCpuUnitStatus> ReadCpuUnitStatus()
        {
            return OmronFinsNetHelper.ReadCpuUnitStatus(this);
        }

        public override string ToString()
        {
            return String.Format("OmronFinsUdp[{0}:{1}]", IpAddress, Port);
        }
    }
}
